//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "DomainPDBHetAtm.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <math.h>

#include <iostream>

#include <zlib.h>
#include <fstream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHLINE 5000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DomainPDBHetAtm::DomainPDBHetAtm () {
  
  this->domain      = new String ();
  
  this->filenameIn  = new String ();
  this->filenameOut = new String ();

  this->chain       = new String ();

  this->listHETATM  = new TListE <String> ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DomainPDBHetAtm::DomainPDBHetAtm (const DomainPDBHetAtm& domainPDBHetAtm) {
  
  this->domain      = new String (domainPDBHetAtm.domain);
  
  this->filenameIn  = new String (domainPDBHetAtm.filenameIn);
  this->filenameOut = new String (domainPDBHetAtm.filenameOut);

  this->chain       = new String (domainPDBHetAtm.chain);

  this->listHETATM  = new TListE <String> (domainPDBHetAtm.listHETATM);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DomainPDBHetAtm::DomainPDBHetAtm (const DomainPDBHetAtm* domainPDBHetAtm) {
  
  this->domain      = new String (domainPDBHetAtm->domain);
  
  this->filenameIn  = new String (domainPDBHetAtm->filenameIn);
  this->filenameOut = new String (domainPDBHetAtm->filenameOut);

  this->chain       = new String (domainPDBHetAtm->chain);

  this->listHETATM  = new TListE <String> (domainPDBHetAtm->listHETATM);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DomainPDBHetAtm::~DomainPDBHetAtm () {
  
  if (this->domain)      delete this->domain;
  
  if (this->filenameIn)  delete this->filenameIn;
  if (this->filenameOut) delete this->filenameOut;

  if (this->chain)       delete this->chain;

  if (this->listHETATM)  delete this->listHETATM;
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DomainPDBHetAtm::Domain (String* domain) {
  
  if (domain) this->domain->In(domain);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DomainPDBHetAtm::FilenameIn (String* filenameIn) {
  
  if (filenameIn) this->filenameIn->In(filenameIn);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DomainPDBHetAtm::FilenameOut (String* filenameOut) {
  
  if (filenameOut) this->filenameOut->In(filenameOut);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DomainPDBHetAtm::Chain (String* chain) {
  
  if (chain) this->chain->In(chain);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DomainPDBHetAtm::ListHETATM (TListE <String>* listHETATM) {
  
  if (listHETATM) *(this->listHETATM) = *(listHETATM);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* DomainPDBHetAtm::Domain (void) {
  
  return this->domain;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* DomainPDBHetAtm::FilenameIn (void) {
  
  return this->filenameIn;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* DomainPDBHetAtm::FilenameOut (void) {
  
  return this->filenameOut;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* DomainPDBHetAtm::Chain (void) {
  
  return this->chain;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* DomainPDBHetAtm::ListHETATM (void) {
  
  return this->listHETATM;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool DomainPDBHetAtm::LoadData (void) {
  
  if (!this->filenameIn || !this->filenameIn->Length() || 
      !this->domain     || !this->domain->Length())
    return false;
  
  String* domain = this->domain->SubStr(4, 5);
  
  this->listHETATM->Clear();
  this->Chain(domain);
  
  if (domain) delete domain;
  
  gzFile pdbFile = gzopen(this->filenameIn->Out(), "rb9");
  
  if (!pdbFile) return false;
  
  char   buffer[LENGTHLINE + 1];
  
  while (!gzeof(pdbFile)) {
    
    gzgets(pdbFile, buffer, LENGTHLINE);
    
    if ((!strncmp(buffer, "HETATM", strlen("HETATM"))) && 
        (buffer[21] == (this->chain->Out())[0])) {
      
      String* line = new String(buffer);
      this->listHETATM->Add(line);
      
    }
    
    if (!strncmp(buffer, "ENDMDL", strlen("ENDMDL")))
      break;
    
  }

  gzclose(pdbFile);
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool DomainPDBHetAtm::OutFile (void) {
  
  if (!this->filenameOut || !this->filenameOut->Length())
    return false;
  
  fstream pdbDomainFile;
  
  pdbDomainFile.open(this->filenameOut->Out(), fstream::out);
  
  this->listHETATM->SetInitial();
  while (this->listHETATM->SetNext())
    pdbDomainFile << this->listHETATM->GetCurrent()->Out();
  
  pdbDomainFile.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DomainPDBHetAtm DomainPDBHetAtm::operator= (const DomainPDBHetAtm& domainPDBHetAtm) {
  
  this->domain->In(domainPDBHetAtm.domain);
  
  this->filenameIn->In(domainPDBHetAtm.filenameIn);
  this->filenameOut->In(domainPDBHetAtm.filenameOut);
  
  this->chain->In(domainPDBHetAtm.chain);
  
  *(this->listHETATM) = *(domainPDBHetAtm.listHETATM);   

  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
